package com.windbell.rest.log

import org.springframework.stereotype.Component
import org.aspectj.lang.annotation.Aspect
import com.windbell.rest.RestRequestInfo
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.ProceedingJoinPoint
import java.util.Date
import java.net.InetAddress
import javax.servlet.http.HttpServletRequest
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.request.ServletRequestAttributes
import org.springframework.beans.factory.annotation.Autowired

@Aspect
@Component
class LoggingAspect {
    
    @Autowired RequestInfoAcceptorFactory factory 
    
    //@Autowired SessionManager sessionManager
    
    @Around("
        within(com.windbell.rest.controllers..*) &&
        execution(public * com.windbell.rest.controllers.*.*(..)) &&
        @annotation(info)")
    def logRequest(ProceedingJoinPoint pjp, RestRequestInfo info){
        val acceptor = factory.createRequestLogAcceptor;
        acceptor.acceptRequestTime(new Date());
        
        val req = (RequestContextHolder.currentRequestAttributes as ServletRequestAttributes).request
        val ip = getUserIP(req);

        acceptor.acceptUserIP(ip)
        acceptor.acceptServiceClass(pjp.signature.declaringTypeName)
        acceptor.acceptServiceMethod(pjp.signature.name)
        acceptor.acceptRequestName(info.name)
            
        //Note: authorization exception is not logged
        try{
            acceptor.acceptBeginSysNanoTime(System.nanoTime)
            val r =  pjp.proceed(pjp.args)
            //user id is available here when it's a login
            val session = req.getSession(false)
            if(session!=null){
            	//acceptor.acceptUserID(sessionManager.getCustomerDTO(session)?.loginId)
            }
            return r
        }catch(Exception e){
            acceptor.acceptException(e);
            throw e;
        }finally{
             acceptor.acceptEndSysNanoTime(System.nanoTime)
             acceptor.finish
        }
    }
    
    
    def private String getUserIP(HttpServletRequest request) {
        var ip = request.getRemoteAddr();
        if (ip.equalsIgnoreCase("0:0:0:0:0:0:0:1")) {
            try{
                val InetAddress inetAddress = InetAddress.getLocalHost();
                val String ipAddress = inetAddress.getHostAddress();
                ip = ipAddress;
            }catch(Exception e){
                
            }
        }
        return ip;
    }
    
}
